package com.example.api.mall.interceptor;

import cn.hutool.core.util.StrUtil;
import com.example.api.mall.utils.TokenUtils;
import com.example.common.core.annotation.NoLoginAuth;
import com.example.common.core.constant.TokenConstant;
import com.example.common.core.exception.LinkerException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @name: MyInterceptor
 * @description: 拦截器
 * 可以通过它来进行权限验证，或者判断用户是否登陆
 * @author: xw.s
 * @date: 2021/5/31-15:10
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * controller中方法执行被调用
     * @param request
     * @param response
     * @param handler
     * @return
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        log.info("preHandle被调用");
        if (!(handler instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        //获取即将执行的方法所属在的对象，类，类中注解
        NoLoginAuth noLoginAuthOnClass = handlerMethod.getBean().getClass().getAnnotation(NoLoginAuth.class);
        if (null != noLoginAuthOnClass){//如果类上有该注解，直接放行
            return true;
        }
        //获取即将执行的方法的注解
        NoLoginAuth noLoginAuth = handlerMethod.getMethod().getAnnotation(NoLoginAuth.class);
        if (null != noLoginAuth){//如果方法上有@NoLoginAuth注解，则不验证是否登录
            return true;
        }
        String token = request.getHeader(TokenConstant.AUTHORIZATION);
        if (StrUtil.isBlank(token)){
            throw new LinkerException("没找到token，请先登录");//虽然拦截器是在controller方法之前调用的，但是依然可以被全局异常处理拦截
        }
        if (!TokenUtils.verifyToken(token)){
            throw new LinkerException("token验证失败");
        }
        log.info("preHandle调用结束");
        return true;
    }

    /**
     * controller方法执行后， 页面被渲染前被调用
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        log.info("postHandle被调用");
        log.info("postHandle调用结束");
    }

    /**
     * 页面被渲染后被调用
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param e
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        log.info("afterCompletion被调用");
        log.info("afterCompletion调用结束");
    }
}
